﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Se.Thread
{
    public class SerialIdGenerator
    {
        /// <summary>
        /// 最大Id
        /// </summary>
        public long MaxSerial { get; private set; }
        /// <summary>
        /// 最小Id
        /// </summary>
        public long MinSerial { get; private set; }

        /// <summary>
        /// 当前的Id
        /// </summary>
        private long _currentSerial;

        /// <summary>
        /// locker
        /// </summary>
        private SpinLock _locker;

        public SerialIdGenerator(long minSerial)
        {
            this.MinSerial = minSerial;
            this._currentSerial = minSerial;
            this.MaxSerial = 0x7fffffffffffffffL;
            this._locker = new SpinLock();
        }

        public SerialIdGenerator(long maxSerial, long minSerial)
            : this(minSerial)
        {
            this.MaxSerial = maxSerial;
        }

        /// <summary>
        /// 新的序列号
        /// </summary>
        /// <returns></returns>
        public long NextSerial()
        {
            SpinLockEx.Enter(ref this._locker);
            long serial;
            try
            {
                serial = Interlocked.Increment(ref this._currentSerial);
                if (serial < this.MinSerial)
                {
                    return this.MinSerial;
                }
                if (serial > this.MaxSerial)
                {
                    serial = this.MaxSerial;
                }
            }
            finally
            {
                SpinLockEx.Exit(ref this._locker);
            }
            return serial;
        }
    }
}
